<!--
 * @Description: 人员基本信息节点组件
 * @Author: Auto
 * @Date: 2025-01-27
-->
<template>
  <div 
    class="person-info-node" 
    :class="nodeClass"
    :style="nodeStyle"
    @mousedown="handleNodeMouseDown"
    @dblclick="handleNodeDoubleClick"
    @dragstart.prevent="handleNodeDragStart"
  >
    <Handle id="top" type="target" position="top" />
    <Handle id="bottom" type="source" position="bottom" />
    <Handle id="left" type="target" position="left" />
    <Handle id="right" type="source" position="right" />
    
    <!-- 删除按钮 -->
    <div class="delete-btn" @click.stop="handleDelete" title="删除节点">
      <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path d="M11 3.5L3 11.5M3 3.5L11 11.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
    </div>
    
    <!-- 添加节点菜单按钮 -->
    <div 
      class="add-menu-btn" 
      @click.stop="toggleMenu($event)"
      title="添加节点"
    >
      <EllipsisOutlined />
      <!-- 下拉菜单 -->
      <div v-if="showMenu" class="add-menu-dropdown" @click.stop>
        <div class="menu-item" @click="handleAddNode('person-info')">
          <span>人员基本信息</span>
        </div>
        <div class="menu-item" @click="handleAddNode('text')">
          <span>文本框</span>
        </div>
        <div class="menu-item" @click="handleAddNode('table')">
          <span>列表信息</span>
        </div>
        <div class="menu-item" @click="handleAddNode('person-trajectory')">
          <span>人像轨迹</span>
        </div>
      </div>
    </div>
    
    <!-- 调整大小拖拽点 -->
    <div 
      class="resize-handle" 
      @mousedown.stop="handleResizeStart"
      title="拖拽调整大小"
    ></div>
    
    <!-- 进度条模式 -->
    <div v-if="progress < 100" class="progress-container">
      <div class="progress-bar-wrapper">
        <div class="progress-bar" :style="{ width: `${progress}%` }"></div>
      </div>
      <div class="progress-text">{{ Math.round(progress) }}%</div>
    </div>
    
    <!-- 节点内容模式 -->
    <template v-else>
      <!-- 空状态 -->
      <div v-if="!idNumber" class="empty-container">
        <a-empty description="暂无数据" />
      </div>
      <!-- 有数据时显示 -->
      <div v-else class="person-info-content">
        <div class="avatar-container">
          <img 
            v-if="avatar" 
            :src="avatar" 
            alt="头像" 
            class="avatar"
            @error="handleImageError"
          />
          <div v-else class="avatar-placeholder">
            <span class="avatar-icon">👤</span>
          </div>
        </div>
        <div class="id-number">
          <span 
            v-if="idNumber" 
            class="id-card-display"
            draggable="true"
            @mousedown.stop="handleIdCardMouseDown"
            @dragstart="handleIdCardDragStart"
            @dragend="handleIdCardDragEnd"
          >
            <svg t="1763026344096" class="icon id-card-icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1615" width="14" height="14">
              <path d="M864.65 336.975v-0.079c56.91 0 98.58 45.804 98.58 102.321v204.485c0 193.26-26.94 349.932-317.283 349.932-127.055 0-187.156-25.363-239.616-68.135a103.778 103.778 0 0 1-19.377-14.966L99.249 624.64c-48.994-49.034-26.584-117.957 7.759-152.222 34.265-34.343 105.433-39.975 145.723 0l62.425 62.307V137.689a102.676 102.676 0 0 1 103.03-102.243c56.91 0 99.643 45.726 99.643 102.243v103.817a102.4 102.4 0 0 1 48.6-12.209c45.293 0 80.463 29.066 94.287 69.317 15.754-9.728 34.856-15.517 54.863-15.517 45.292 0 80.384 29.065 94.208 69.395a95.31 95.31 0 0 1 52.145-15.517h2.757z m44.19 306.727v0.158h0.236V445.755c0-50.333-47.301-48.364-47.301-48.364-26.94 0-46.986 21.661-46.986 48.364v106.417h-0.551a31.114 31.114 0 0 1 0.55 5.435 26.466 26.466 0 0 1-26.544 26.86 27.018 27.018 0 0 1-26.546-32.295h-0.55v-156.12c0-45.332-48.76-48.404-48.76-48.404-26.938 0-46.08 21.7-46.08 48.404v123.943h-0.63a26.978 26.978 0 0 1-26.505 32.295 27.018 27.018 0 0 1-26.545-32.295h-0.552V342.37c0-49.112-47.773-48.443-47.773-48.443-26.94 0-46.474 21.662-46.474 48.443v134.538h-0.512a26.978 26.978 0 0 1-26.624 32.296 27.018 27.018 0 0 1-26.545-32.296h-0.512v-328.35c0-26.702-18.432-48.442-45.371-48.442-27.018 0-48.837 21.74-48.837 48.443v516.214c-49.231-48.837-98.383-97.753-147.535-146.629-19.062-18.905-55.257-18.196-74.949 1.575-19.653 19.693-25.758 50.452-1.694 74.595l272.306 270.533c50.53 50.176 117.248 74.91 228.234 74.91 262.262 0 263.05-132.53 263.05-296.055z" p-id="1616" fill="#1890ff"></path>
            </svg>
            <span class="id-card-text">{{ idNumber }}</span>
          </span>
          <span v-else>证件号码：未设置</span>
        </div>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, onUnmounted, onMounted } from 'vue'
import { Handle } from '@vue-flow/core'
import { EllipsisOutlined } from '@ant-design/icons-vue'

Handle.name = 'Handle'

interface Props {
  avatar?: string // 头像URL
  idNumber?: string // 证件号码
  progress?: number // 进度 0-100
  nodeId?: string
  width?: number
  height?: number
  selected?: boolean // 是否选中
}

const props = withDefaults(defineProps<Props>(), {
  avatar: '',
  idNumber: '',
  progress: 100,
  nodeId: '',
  width: undefined,
  height: undefined,
  selected: false
})

const emit = defineEmits<{
  delete: [nodeId: string]
  resize: [nodeId: string, width: number, height: number]
  addNode: [nodeId: string, nodeType: 'person-info' | 'text' | 'table' | 'person-trajectory']
  createPersonNode: [idNumber: string]
}>()

// 菜单显示状态
const showMenu = ref(false)

// 切换菜单显示
const toggleMenu = (e: MouseEvent) => {
  showMenu.value = !showMenu.value
}

// 处理添加节点
const handleAddNode = (nodeType: 'person-info' | 'text' | 'table' | 'person-trajectory') => {
  if (props.nodeId) {
    emit('addNode', props.nodeId, nodeType)
    showMenu.value = false
  }
}

// 点击外部关闭菜单
onMounted(() => {
  const handleClickOutside = (e: MouseEvent) => {
    if (showMenu.value) {
      const target = e.target as HTMLElement
      if (!target.closest('.add-menu-btn') && !target.closest('.add-menu-dropdown')) {
        showMenu.value = false
      }
    }
  }
  document.addEventListener('click', handleClickOutside)
  
  onUnmounted(() => {
    document.removeEventListener('click', handleClickOutside)
  })
})

const nodeClass = computed(() => ({
  'node-person-info': true,
  'node-selected': props.selected
}))

const nodeStyle = computed(() => {
  const style: Record<string, string> = {}
  if (props.width !== undefined) {
    style.width = `${props.width}px`
  }
  if (props.height !== undefined) {
    style.height = `${props.height}px`
  }
  return style
})

const handleDelete = () => {
  if (props.nodeId) {
    emit('delete', props.nodeId)
  }
}

// 调整大小相关
const isResizing = ref(false)
const startX = ref(0)
const startY = ref(0)
const startWidth = ref(0)
const startHeight = ref(0)

const handleResizeStart = (e: MouseEvent) => {
  e.preventDefault()
  e.stopPropagation()
  isResizing.value = true
  startX.value = e.clientX
  startY.value = e.clientY
  startWidth.value = props.width || 200
  startHeight.value = props.height || 150
  
  document.addEventListener('mousemove', handleResizeMove)
  document.addEventListener('mouseup', handleResizeEnd)
  document.body.style.userSelect = 'none'
  document.body.style.cursor = 'nwse-resize'
}

const handleResizeMove = (e: MouseEvent) => {
  if (!isResizing.value) return
  const deltaX = e.clientX - startX.value
  const deltaY = e.clientY - startY.value
  const newWidth = Math.max(180, startWidth.value + deltaX)
  const newHeight = Math.max(120, startHeight.value + deltaY)
  emit('resize', props.nodeId, newWidth, newHeight)
}

const handleResizeEnd = () => {
  isResizing.value = false
  document.removeEventListener('mousemove', handleResizeMove)
  document.removeEventListener('mouseup', handleResizeEnd)
  document.body.style.userSelect = ''
  document.body.style.cursor = ''
}

onUnmounted(() => {
  document.removeEventListener('mousemove', handleResizeMove)
  document.removeEventListener('mouseup', handleResizeEnd)
})

const handleImageError = () => {
  // 图片加载失败时的处理
}

// 处理节点鼠标按下事件 - 确保拖拽功能正常
const handleNodeMouseDown = (e: MouseEvent) => {
  // 如果点击的是按钮、调整大小拖拽点或身份证号码，不阻止事件
  const target = e.target as HTMLElement
  if (
    target.closest('.delete-btn') ||
    target.closest('.add-menu-btn') ||
    target.closest('.add-menu-dropdown') ||
    target.closest('.resize-handle') ||
    target.closest('.vue-flow__handle') ||
    target.closest('.id-card-display')
  ) {
    // 这些元素的事件已经通过 @click.stop 或 @mousedown.stop 处理了
    return
  }
  // 其他区域允许拖拽，不阻止默认行为
}

// 处理身份证号码鼠标按下事件 - 阻止节点拖拽
const handleIdCardMouseDown = (e: MouseEvent) => {
  e.stopPropagation() // 阻止事件冒泡，防止触发节点拖拽
  // 注意：不要调用 preventDefault()，否则会阻止拖拽开始
  // e.preventDefault() // 移除这行，让拖拽能正常开始
  console.log('身份证号码 mousedown', { idNumber: props.idNumber })
}

// 处理节点拖拽开始 - 如果是身份证号码拖拽，则阻止节点拖拽
const handleNodeDragStart = (e: DragEvent) => {
  const target = e.target as HTMLElement
  // 如果拖拽的是身份证号码，阻止节点拖拽
  if (target.closest('.id-card-display')) {
    e.preventDefault()
    e.stopPropagation()
    e.stopImmediatePropagation()
    return false
  }
}

// 处理节点双击事件
const handleNodeDoubleClick = (e: MouseEvent) => {
  // 如果点击的是按钮或调整大小拖拽点，不处理双击
  const target = e.target as HTMLElement
  if (
    target.closest('.delete-btn') ||
    target.closest('.add-menu-btn') ||
    target.closest('.add-menu-dropdown') ||
    target.closest('.resize-handle') ||
    target.closest('.vue-flow__handle')
  ) {
    return
  }
  console.log('Node double clicked in component:', props.nodeId)
  // 可以在这里添加节点编辑逻辑
  // 注意：事件会继续冒泡到 Vue Flow 的 @node-dblclick 事件
}

// 处理身份证号码拖拽开始
const handleIdCardDragStart = (e: DragEvent) => {
  console.log('身份证号码拖拽开始', { idNumber: props.idNumber, nodeId: props.nodeId })
  
  // 阻止节点拖拽，但不阻止拖拽事件本身
  e.stopPropagation() // 阻止冒泡到节点
  
  if (!props.idNumber || !e.dataTransfer) {
    console.log('没有身份证号码或 dataTransfer')
    e.preventDefault()
    return false
  }
  
  // 设置拖拽数据
  e.dataTransfer.effectAllowed = 'copy'
  e.dataTransfer.setData('text/plain', props.idNumber)
  e.dataTransfer.setData('application/id-card', props.idNumber)
  e.dataTransfer.setData('source-node-id', props.nodeId || '')
  
  console.log('拖拽数据已设置', { 
    types: e.dataTransfer.types,
    effectAllowed: e.dataTransfer.effectAllowed 
  })
  
  // 添加拖拽时的视觉反馈
  const target = e.target as HTMLElement
  const idCardElement = target.closest('.id-card-display') as HTMLElement
  if (idCardElement) {
    idCardElement.style.opacity = '0.5'
  }
  
  // 不要返回 false，让拖拽继续
}

// 处理身份证号码拖拽结束
const handleIdCardDragEnd = (e: DragEvent) => {
  // 注意：不要在这里阻止事件冒泡，因为 drop 事件需要在 dragend 之前触发
  // e.stopPropagation() // 移除这行，让 drop 事件能够正常触发
  
  // 恢复视觉反馈
  const target = e.target as HTMLElement
  const idCardElement = target.closest('.id-card-display') as HTMLElement
  if (idCardElement) {
    idCardElement.style.opacity = '1'
  }
  
  console.log('拖拽结束')
}
</script>

<style scoped lang="less">
.person-info-node {
  padding: 12px;
  border-radius: 8px;
  min-width: 172px; // 148px照片 + 24px内边距（左右各12px）
  width: 172px; // 固定宽度以适应照片
  min-height: 228px; // 168px照片 + 60px其他内容（证件号等）
  height: auto;
  background: #ffffff;
  border: 2px solid #faad14; // 改为黄色
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: box-shadow 0.3s ease, border-color 0.3s ease;
  cursor: grab; // 改为grab，提示可以拖拽
  position: relative;
  overflow: visible; // 改为visible，确保按钮不被裁剪
  box-sizing: border-box;
  
  &:active {
    cursor: grabbing; // 拖拽时显示grabbing
  }
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;

  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
  }

  // 选中状态样式
  &.node-selected {
    border-color: #1890ff;
    border-width: 3px;
    box-shadow: 0 0 0 3px rgba(24, 144, 255, 0.2), 0 4px 16px rgba(24, 144, 255, 0.3);
  }

  :deep(.vue-flow__handle) {
    width: 4px !important;
    height: 4px !important;
    background: #faad14 !important; // 改为黄色
    border: 2px solid #ffffff !important;
    border-radius: 50% !important;
    z-index: 1000 !important;
    opacity: 0.9;
    cursor: crosshair !important;
    pointer-events: auto !important;
    padding: 4px !important;
    margin: -4px !important;
    box-sizing: content-box !important;
    position: absolute !important;

    &:hover {
      opacity: 1 !important;
      background: #ffc53d !important; // 改为黄色hover状态
      box-shadow: 0 0 8px rgba(250, 173, 20, 0.6) !important;
      z-index: 1001 !important;
    }
  }

  .delete-btn {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 20px;
    height: 20px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.9);
    border-radius: 4px;
    cursor: pointer;
    z-index: 1002;
    opacity: 1; // 一直显示
    transition: background-color 0.2s ease;
    color: #8c8c8c;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);

    &:hover {
      background: #ff4d4f;
      color: #ffffff;
    }
  }

  // 添加节点菜单按钮
  .add-menu-btn {
    position: absolute !important;
    top: 4px !important;
    right: 28px !important; // 放在删除按钮左侧4px：删除按钮right:4px + width:20px + 间距4px = 28px
    width: 20px !important;
    height: 20px !important;
    display: flex !important;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.95) !important;
    border-radius: 4px;
    cursor: pointer;
    z-index: 1003 !important; // 提高层级，确保在删除按钮之上
    opacity: 1 !important; // 一直显示，强制显示
    visibility: visible !important; // 确保可见
    transition: background-color 0.2s ease;
    color: #8c8c8c !important;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15) !important;
    pointer-events: auto !important; // 确保可以点击
    border: 1px solid rgba(0, 0, 0, 0.1); // 添加边框，更容易看到

    &:hover {
      background: #faad14 !important; // 改为黄色
      color: #ffffff !important;
      border-color: #faad14 !important;
    }

    .add-menu-dropdown {
      position: absolute; // 相对于按钮定位
      top: calc(100% + 4px); // 紧贴按钮下方4px
      left: 0; // 右对齐到按钮右边缘
      background: #ffffff;
      border-radius: 4px;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
      min-width: 140px;
      z-index: 10000; // 提高层级确保在最上层
      overflow: hidden;
      margin: 0; // 移除所有默认margin
      padding: 0; // 移除默认padding
      transform: none;

      .menu-item {
        padding: 8px 12px;
        cursor: pointer;
        font-size: 14px;
        color: #262626;
        transition: background-color 0.2s ease;
        white-space: nowrap; // 防止文字换行

        &:hover {
          background: #f0f0f0;
        }

        &:not(:last-child) {
          border-bottom: 1px solid #f0f0f0;
        }
      }
    }
  }

  .resize-handle {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 12px;
    height: 12px;
    background: #faad14; // 改为黄色
    border: 2px solid #ffffff;
    border-radius: 50%;
    cursor: nwse-resize;
    z-index: 1002;
    opacity: 0;
    transition: opacity 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
    transform: translate(50%, 50%);

    &:hover {
      opacity: 1 !important;
      background: #ffc53d; // 改为黄色hover状态
      box-shadow: 0 0 8px rgba(250, 173, 20, 0.6);
    }

    &:active {
      background: #d48806; // 改为黄色active状态
    }
  }

  &:hover .resize-handle {
    opacity: 0.8;
  }

  .progress-container {
    width: 100%;
    height: 100%;
    padding: 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 200px;
    min-height: 120px;
    box-sizing: border-box;
  }

  .progress-bar-wrapper {
    width: 100%;
    height: 8px;
    background: #f0f0f0;
    border-radius: 4px;
    overflow: hidden;
    margin-bottom: 12px;
  }

  .progress-bar {
    height: 100%;
    background: linear-gradient(90deg, #faad14 0%, #ffc53d 100%); // 改为黄色
    border-radius: 4px;
    transition: width 0.1s linear;
  }

  .progress-text {
    font-size: 14px;
    font-weight: 600;
    color: #faad14; // 改为黄色
  }

  .empty-container {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    padding: 20px;
  }

  .person-info-content {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap: 12px;
    box-sizing: border-box;
    padding: 0;
  }

  .avatar-container {
    width: 148px; // 185 * 0.8 = 148px
    height: 168px; // 210 * 0.8 = 168px
    border-radius: 8px; // 添加圆角
    overflow: hidden;
    border: 2px solid #faad14; // 改为黄色
    background: #f0f0f0;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;

    .avatar {
      width: 100%;
      height: 100%;
      object-fit: cover; // 保持比例，裁剪多余部分
    }

    .avatar-placeholder {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      background: linear-gradient(135deg, #ffe58f 0%, #ffd666 100%); // 改为黄色渐变

      .avatar-icon {
        font-size: 60px; // 增大图标以适应更大的容器
      }
    }
  }

  .id-number {
    font-size: 14px;
    color: #262626;
    text-align: center;
    word-break: break-all;
    padding: 0;
    width: 100%;
    flex-shrink: 0;

    .id-card-display {
      display: inline-flex;
      align-items: center;
      gap: 4px;
    }

    .id-card-icon {
      display: inline-block;
      vertical-align: middle;
      margin-right: 4px;
      
      path {
        fill: #1890ff;
      }
    }

    .id-card-text {
      color: #1890ff;
      font-weight: 500;
    }
    
    .id-card-display {
      cursor: grab;
      user-select: none;
      transition: opacity 0.2s ease;
      position: relative;
      z-index: 10; // 提高层级，确保在节点之上
      pointer-events: auto; // 确保可以接收鼠标事件
      
      &:hover {
        opacity: 0.8;
      }
      
      &:active {
        cursor: grabbing;
      }
      
      // 确保内部的 SVG 和文本也能触发拖拽
      svg,
      .id-card-text {
        pointer-events: none; // 让事件冒泡到父元素
      }
    }
  }
}
</style>

